﻿using System;
using System.Collections.Generic;
using Supermodel.Exceptions;

namespace Supermodel.UOW
{
    public static class UnitOfWorkContext<T> where T: UnitOfWork
    {
        #region Methods and Properties
        static public T PopUnitOfWork()
        {
            return (T)UnitOfWorkContextCore.PopUnitOfWork();
        }

        static public void PushUnitOfWork(T uow)
        {
            UnitOfWorkContextCore.PushUnitOfWork(uow);
        }

        public static uint StackCount
        {
            get { return UnitOfWorkContextCore.StackCount; }
        }

        static public T CurrentUnitOfWork
        {
            get { return (T)UnitOfWorkContextCore.CurrentUnitOfWork; }
        } 
        #endregion
    }

    public static class UnitOfWorkContextCore
    {
        #region Methods and Properties
        static public UnitOfWork PopUnitOfWork()
        {
            return _unitOfWorkDbContextStack.Pop();
        }

        static public void PushUnitOfWork(UnitOfWork uow)
        {
            _unitOfWorkDbContextStack.Push(uow);
        }

        public static uint StackCount
        {
            get { return (uint)_unitOfWorkDbContextStack.Count; }
        }

        static public UnitOfWork CurrentUnitOfWork
        {
            get
            {
                try
                {
                    return _unitOfWorkDbContextStack.Peek();
                }
                catch (InvalidOperationException)
                {
                    throw new SupermodelException("Current UnitOfWork does not exist. All database access oprations must be wrapped in 'using(new UnitOfWork())'");
                }
            }
        }
        #endregion

        #region Private variables
        static private readonly Stack<UnitOfWork> _unitOfWorkDbContextStack = new Stack<UnitOfWork>();
        #endregion
    }
}
